﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Data;
using Microsoft.Office.Server.Search;
using Microsoft.Office.Server.Search.Query;
using Microsoft.Office.Server.Search.Administration;
using Microsoft.Office.Server;
using Microsoft.Office.Server.Diagnostics;

namespace SPDEV.Search.Utilities
{
    /// <summary>
    /// This page shows hidden properties known about managed properties.
    /// </summary>
    public class DisplayHiddenAttributesOfSearchMetadataAdminLayoutsPage : LayoutsPageBase
    {
        #region Constants
        const string Title = "Title";
        const string FullTextQueriable = "FullTextQueriable";
        const string Retrievable = "Retrievable";
        const string Type = "type";
        const string Weight = "Weight";
        const string DocumentsFound = "DocumentsFound";
        const string CrawledProperties = "CrawledProperties";
        #endregion

        // Controls
        protected SPGridView gridView;

        // ivars
        private SearchContext SearchContext { get; set; }
        private ServerContext ServerContext { get; set; }
        private SPSite CurrentSite { get; set; }

        #region Ctrs / Init

        /// <summary>
        /// Used for testing
        /// </summary>
        /// <param name="searchContext"></param>
        /// <param name="serverContext"></param>
        /// <param name="currentSite"></param>
        public DisplayHiddenAttributesOfSearchMetadataAdminLayoutsPage(SearchContext searchContext, ServerContext serverContext, SPSite currentSite)
        {
            this.ServerContext = serverContext;
            this.SearchContext = searchContext;
            this.CurrentSite = currentSite;
        }

        public DisplayHiddenAttributesOfSearchMetadataAdminLayoutsPage()
            : base()
        {
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            this.CurrentSite = SPContext.Current.Site;
            this.ServerContext = ServerContext.GetContext(this.CurrentSite);
            this.SearchContext = SearchContext.GetContext(ServerContext);

            DataTable dataTable = CreateDataTable();

            gridView.DataSource = dataTable;
            gridView.DataBind();
        }

        #endregion

        /// <summary>
        /// Create DataTable with columns, and bind to properties retrieved for current context
        /// </summary>
        /// <returns></returns>
        public DataTable CreateDataTable()
        {
            DataTable dataTable = new DataTable();
            dataTable.AddColumns(new string[] 
            { 
                Title, FullTextQueriable, Retrievable, Type, Weight, DocumentsFound, CrawledProperties
            });

            using (FullTextSqlQuery query = new FullTextSqlQuery(ServerContext))
            {
                foreach (var property in query.GetProperties())
                {
                    var row = GenerateRowOrNullForProperty(dataTable, property);
                    if (null != row)
                        dataTable.Rows.Add(row);
                }
            }
            return dataTable;
        }

        /// <summary>
        /// Create a row in the datatable, for each managed property.
        /// </summary>
        /// <param name="dataTable"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        private DataRow GenerateRowOrNullForProperty(DataTable dataTable, PropertyInformation property)
        {
            try
            {
                var managedProperty = SearchContext.GetManagedProperty(property.Name);
                if (managedProperty != null)
                {
                    DataRow row = dataTable.NewRow();

                    row[Title] = property.Name;
                    row[FullTextQueriable] = property.FullTextQueriable;
                    row[Retrievable] = property.Retrievable;
                    row[Type] = property.Type.Name;
                    row[Weight] = string.Format("{0}", managedProperty.Weight);
                    row[CrawledProperties] = string.Format("{0}", managedProperty.GetMappings().Count);

                    bool exceededLimit = false;
                    int docsFoundCount = managedProperty.GetDocumentsFound(ref exceededLimit);
                    row[DocumentsFound] = exceededLimit ? string.Format("> {0}", docsFoundCount) : string.Format("{0}", docsFoundCount);

                    return row;
                }
            }
            catch (Exception ex)
            {
                // problem with a single managed property
                PortalLog.LogString("CustomSearch: ManagedProperty Attributes: Error creating row with name: {0}", property.Name);
            }
            return null;
        }
    }
}
